﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace SpriteClasses
{
    public class SpriteFromSheet2 : Sprite
    {
        protected Vector2 initialFrame = Vector2.Zero;
        private bool onePlay = false; // for a quick animation that plays once
        private bool onePlayW_Speed = false; // for a quick animation that plays once with speed variable
        private bool stopAnimation = false;

        // quick animation temps
        private Vector2 quickStart;
        private Vector2 quickEnd;
        private float quickFrameSpeed = 0;
        //-------------------------------
        protected Vector2 frameSize;      // Size of frames in sprite sheet
        public Vector2 FrameSize
        {
            get { return frameSize; }
            set { frameSize = value; }
        }
        protected Vector2 currentFrame;   // Index of current frame in sprite sheet
        public Vector2 CurrentFrame
        {
            get { return currentFrame; }
            set { currentFrame = value; }
        }
        protected Vector2 endFrame;   // Index of current frame in sprite sheet
        public Vector2 EndFrame
        {
            get { return endFrame; }
            set { endFrame = value; }
        }
        protected Vector2 sheetSize;      // Number of columns and rows in the sprite sheet
        public Vector2 SheetSize
        {
            get { return sheetSize; }
            set { sheetSize = value; }
        }

        private float TimeToNextFrame { get; set; } // Time when we need to goto next frame

        private float ElapsedTime { get; set; } // time so far towards next frame

        public override Rectangle CollisionRectangle
        {
            get
            {
                return new Rectangle((int)position.X, (int)position.Y, (int)FrameSize.X, (int)FrameSize.Y);
            }
        }

        public SpriteFromSheet2(Texture2D textureImage, Vector2 position, Vector2 velocity,
            float rotationSpeed, float scale, SpriteEffects spriteEffect, float moveSpeed,
            Vector2 frameSize, Vector2 currentFrame, Vector2 endFrame, Vector2 sheetSize, float delayBetweenFrames)
            : base(textureImage, position, velocity, rotationSpeed, scale, spriteEffect, moveSpeed)
        {
            FrameSize = frameSize;
            CurrentFrame = currentFrame;
            initialFrame = currentFrame;
            EndFrame = endFrame;
            SheetSize = sheetSize;
            //time to next frame is total time to play the sheet divided by number of frames
            TimeToNextFrame = delayBetweenFrames;

            SpriteOrigin = new Vector2(FrameSize.X / 2, FrameSize.Y / 2);
        }


        public void changeFrameStartAndEnd(Vector2 start, Vector2 end) // change the frames
        {
            initialFrame = start;
            CurrentFrame = start;
            endFrame = end;
        }
        public void changeFrameStartAndEnd(Vector2 start, Vector2 end, float timeToNextFrame) // change the frames with delay
        {
            initialFrame = start;
            CurrentFrame = start;
            endFrame = end;
            TimeToNextFrame = timeToNextFrame;
        }
        public void playOnce(Vector2 start, Vector2 end)
        {
            onePlay = true;
            quickStart = start;
            currentFrame = start;
            quickEnd = end;
            
        }
        public void playOnce(Vector2 start, Vector2 end, float speed)
        {
            onePlayW_Speed = true;
            quickStart = start;
            currentFrame = start;
            quickEnd = end;
        }
        public void togglePause() // toggles the animation to pause or not
        {
            if (!stopAnimation)
            {
                stopAnimation = true;
            }
            else
            {
                stopAnimation = false;
            }
        }


        public override void Update(GameTime gameTime)
        {
            //call base method to do rotation and basic movement
            base.Update(gameTime);
            //how long since last frame displayed
            ElapsedTime += (float)gameTime.ElapsedGameTime.TotalSeconds;
            //if it's time to display the next one, do so, then reset time back to 0
            if (!stopAnimation)
            {
                if (!onePlay && !onePlayW_Speed)
                {
                    if (ElapsedTime > TimeToNextFrame)
                    {
                        if (currentFrame.X >= sheetSize.X)
                        {
                            currentFrame.X = 0;
                            if (currentFrame.Y >= sheetSize.Y)
                            {
                                currentFrame.Y = 0;
                            }
                            else
                            {
                                currentFrame.Y++;
                            }
                        }
                        else
                        {
                            currentFrame.X++;
                        }

                        ElapsedTime = 0f;
                    }
                    if (currentFrame == endFrame)
                    {
                        currentFrame = initialFrame;
                    }
                }
                if (onePlay) // one play without changing time to next frame
                {
                    if (ElapsedTime > TimeToNextFrame)
                    {
                        if (currentFrame.X >= sheetSize.X)
                        {
                            currentFrame.X = 0;
                            if (currentFrame.Y >= sheetSize.Y)
                            {
                                currentFrame.Y = 0;
                            }
                            else
                            {
                                currentFrame.Y++;
                            }
                        }
                        else
                        {
                            currentFrame.X++;
                        }

                        ElapsedTime = 0f;
                    }
                    if (currentFrame == quickEnd)
                    {
                        onePlay = false;
                        currentFrame = initialFrame;
                    }
                }
                if (onePlayW_Speed) // one play with changing time to next frame
                {
                    if (ElapsedTime > quickFrameSpeed)
                    {
                        if (currentFrame.X >= sheetSize.X)
                        {
                            currentFrame.X = 0;
                            if (currentFrame.Y >= sheetSize.Y)
                            {
                                currentFrame.Y = 0;
                            }
                            else
                            {
                                currentFrame.Y++;
                            }
                        }
                        else
                        {
                            currentFrame.X++;
                        }

                        ElapsedTime = 0f;
                    }
                    if (currentFrame == quickEnd)
                    {
                        onePlayW_Speed = false;
                        currentFrame = initialFrame;
                    }
                }
            }
        }
        public override void Update(GameTime gameTime, GraphicsDevice Device)
        {
            if (Active)
            {
                //call overload to do rotation, basic movement and frame updating
                Update(gameTime);
                //keep on screen
                if (Position.X > Device.Viewport.Width - FrameSize.X + SpriteOrigin.X)
                {
                    //GraphicsDevice.Viewport.Width or Window.ClientBounds.Width will both give us the width of the screen
                    position.X = Device.Viewport.Width - FrameSize.X + SpriteOrigin.X;
                }
                else if (Position.X < SpriteOrigin.X)
                {
                    position.X = SpriteOrigin.X;
                }

                if (Position.Y > Device.Viewport.Height - FrameSize.Y + SpriteOrigin.Y)
                {
                    position.Y = Device.Viewport.Height - FrameSize.Y + SpriteOrigin.Y;
                }
                else if (Position.Y < SpriteOrigin.Y)
                {
                    position.Y = SpriteOrigin.Y;
                }
            }
        }
        public void Draw(GameTime gameTime, SpriteBatch spriteBatch, Color color)
        {
            spriteBatch.Draw(TextureImage,
                             Position,
                             new Rectangle((int)(currentFrame.X * frameSize.X),
                                           (int)(currentFrame.Y * frameSize.Y),
                                           (int)frameSize.X,
                                           (int)frameSize.Y),
                             color,
                             Rotation,
                             SpriteOrigin,
                             Scale,
                             SpriteEffect,
                             0);
        }
        public override bool IsOffScreen(GraphicsDevice Device)
        {
            if (Position.X < -FrameSize.X ||
                Position.X > Device.Viewport.Width ||
                Position.Y < -FrameSize.Y ||
                Position.Y > Device.Viewport.Height)
            {
                return true;
            }
            return false;
        }

    }
}
